`timescale 1 ns /  100 ps
module fifo
(
	clock,
	resetn,
	
	writeenable,
	writedata,
	readenable,
	readdata,
	
	empty,
	full,

	count
);

parameter WIDTH = 8;

input clock, resetn, writeenable, readenable;
input [WIDTH - 1:0] writedata;
output [WIDTH - 1:0] readdata;
output empty, full;
output reg[9:0] count;
// fifo buffer
reg  [WIDTH - 1:0] fifo_buffer [1023:0];
reg [9:0] tail, head;
wire increment, decrement;

// control logic
assign empty = (count == 10'd0) ? 1'b1 : 1'b0;
assign full = (count == 10'd1023) ? 1'b1 : 1'b0;

assign increment = (writeenable == 1 && full == 0);
assign decrement = (readenable == 1 && empty == 0);

assign readdata = decrement ? fifo_buffer[tail] : 8'b0;

// write to fifo buffer
always @(posedge clock)
begin
	if (increment)
		fifo_buffer[head] = writedata;
end
		

// counter
always @(posedge clock or negedge resetn)
begin
	if (resetn == 0)
		count <= 10'd0;
	else if (increment && !decrement)
		count <= count + 8'b1;
	else if (decrement && !increment)
		count <= count - 8'b1;
end

// tail, head
always @(posedge clock or negedge resetn)
begin
	if (resetn == 0)
	begin
		tail <= 0;
		head <= 0;
	end
	else
	begin
		if (increment)
			head <= head + 8'b1;
		if (decrement)
			tail <= tail + 8'b1;
	end
end

endmodule
